const axios = require('axios');
const cache = require('./cacheUtils')
const {logger}=require("./logger");//日志记录
// 工具函数
/**
 * 时间格式化函数
 * @param dateStr 时间戳
 * @param format YYYY MM DD hh mm ss 随意拼接符组合
 * @return {*}
 */
const dateFormat = (dateStr, format) =>{
    const date = new Date(dateStr);
    const year = date.getFullYear();
    const month = date.getMonth() + 1;
    const day = date.getDate();
    const hours = date.getHours();
    const minutes = date.getMinutes();
    const seconds = date.getSeconds();

    const map = {
        'M': String(month),
        'MM': String(month).padStart(2, '0'),
        'D': String(day),
        'DD': String(day).padStart(2, '0'),
        'h': String(hours),
        'hh': String(hours).padStart(2, '0'),
        'm': String(minutes),
        'mm': String(minutes).padStart(2, '0'),
        's': String(seconds),
        'ss': String(seconds).padStart(2, '0'),
        'YYYY': String(year),
        'YY': String(year).slice(-2),
    };

    return format.replace(/M+|D+|h+|m+|s+|Y+/g, (match) => {
        return map[match];
    });
}


/**
 * decodedData
 * @param encodedData 加密数据
 * @return {string}
 */
function base64Decode(encodedData) {
    const b64 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
    let o1, o2, o3, h1, h2, h3, h4, bits, i = 0, ac = 0, dec = '', tmpArr = [];

    encodedData = encodedData.replace(/[^A-Za-z0-9+/=]/g, '');

    do {
        h1 = b64.indexOf(encodedData.charAt(i++));
        h2 = b64.indexOf(encodedData.charAt(i++));
        h3 = b64.indexOf(encodedData.charAt(i++));
        h4 = b64.indexOf(encodedData.charAt(i++));

        bits = (h1 << 18) | (h2 << 12) | (h3 << 6) | h4;

        o1 = (bits >> 16) & 0xff;
        o2 = (bits >> 8) & 0xff;
        o3 = bits & 0xff;

        tmpArr[ac++] = String.fromCharCode(o1, o2, o3);

        if (h4 === 64) {
            tmpArr[ac - 1] = String.fromCharCode(o1, o2);
        }
        if (h3 === 64) {
            tmpArr[ac - 1] = String.fromCharCode(o1);
        }
    } while (i < encodedData.length);

    dec = tmpArr.join('');
    dec = utf8Decode(dec);
    return dec;
}

/**
 * utf8Decode
 * @param utftext
 * @return {string}
 */
function utf8Decode(utftext) {
    let string = '';
    let i = 0;
    let c = 0;
    let c2 = 0;
    let c3 = 0;

    while (i < utftext.length) {
        c = utftext.charCodeAt(i);

        if (c < 128) {
            string += String.fromCharCode(c);
            i++;
        } else if ((c > 191) && (c < 224)) {
            c2 = utftext.charCodeAt(i + 1);
            string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
            i += 2;
        } else {
            c2 = utftext.charCodeAt(i + 1);
            c3 = utftext.charCodeAt(i + 2);
            string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
            i += 3;
        }
    }
    return string;
}

function getGeoInfo(ip) {
    if(ip==='::1'){
        // localhost
        return Promise.resolve({
            infocode: '',
            province: '',
            city: '',
            rectangle: '',
            district: '',
            status: '1',
            info: 'OK',
            adcode: ''
        } )
    }
    let ipAddress = {
        infocode: '',
        province: '',
        city: '',
        rectangle: '',
        district:''
    }
    return new Promise(async (resolve, reject) => {
        try {

            const cacheResult = await cache.getCache(ip)
            if(cacheResult){
                Object.assign(ipAddress,cacheResult)
                resolve(ipAddress)
                return
            }
            // console.log('ip=>startRequest',ip)
            const response = await axios.get(`https://restapi.amap.com/v3/ip?ip=${ip}&output=json&key=ac627cc80b149eadc10210c06a3055ec`).catch(error => {
                console.error('ip解析', error);
                resolve(ipAddress);
                logger.error({
                    msg:'restapi.amap.com/v3/ip失败',
                    ip,
                    err:error
                })
            });
            //{"status":"1","info":"OK","infocode":"10000","province":[],"city":[],"adcode":[],"rectangle":[]}
            //上面这种返回的不存缓存，并重置成正确格式字符串
            // {"status":"1","info":"OK","infocode":"10000","province":"北京市","city":"北京市","adcode":"110000","rectangle":"116.0119343,39.66127144;116.7829835,40.2164962"}
            let responseData = response.data
            for (let key in responseData) {
                if (Array.isArray(responseData[key])) {
                    responseData[key] = "";
                }
            }
            if(responseData.status === '1'  && responseData?.province
                && responseData?.city && responseData?.adcode && responseData?.rectangle
            ){
                cache.setCache(ip,responseData)
                Object.assign(ipAddress,responseData)
            }
            // 打印查询结果
            resolve(ipAddress);
        } catch (error) {
            logger.error({
                err:error,
                msg:'getGeoInfo-catch失败'
            })
            resolve(ipAddress);
        }
    });
}

/**
 * @method 获取客户端IP地址
 * @param {string} req 传入请求HttpRequest
 * 客户请求的IP地址存在于request对象当中
 * express框架可以直接通过 req.ip 获取
 */
function getClientIp(req) {
    let ip =  req.headers['x-forwarded-for'] ||
        req.ip ||
        req.connection.remoteAddress ||
        req.socket.remoteAddress ||
        req.connection.socket.remoteAddress ||
        '';
    // 处理ipv6
    if(ip.split(',').length>0){
        ip = ip.split(',')[0];
    }
    return ip
}
const getHeader = (req,field) =>{
    return decodeURIComponent( req.header(field))
}
module.exports = {
    dateFormat,
    base64Decode,
    getGeoInfo,
    getClientIp,
    getHeader
};
